package com.pic.mgt.executer;

import com.pic.mgt.log.IgxLog;
import com.pic.mgt.queue.QueueService;
import com.pic.mgt.unit.Unit;

/**
 * 單元指派器，負責將 Unit 指定給正確的 UnitExecuter 執行。
 * @author 洪政緯
 *
 */
public abstract class UnitDispatcher {
	
	private UnitQueueService unitQueueService;
	
	public UnitDispatcher() {
		if (adoptQueueService()) {
			this.unitQueueService = new UnitQueueService();
			this.unitQueueService.startQueueService();
		}
	}
	
	public void sendToUnitExecuter(Unit unit) {
		// ********************** Log **********************
		if (IgxLog.messageDetailsLog.isTraceMode()) {
			IgxLog.messageDetailsLog
					.trace(this, "Received an unit '{}' to be executed.", unit
							.getUnitName());
		}
		// ********************** Log **********************
		
		if (adoptQueueService()) {
			this.unitQueueService.putElementInQueue(unit);
		}
		else {
			execute(unit);
		}
	}
	
	/**
	 * 將 Unit 交給對應的 UnitExecuter 去執行。
	 * @param unit
	 */
	protected abstract void execute(Unit unit);
	
	/**
	 * 指定此 UnitDispatcher 是否要採用 Queue 的服務方式來運作；
	 * 若不使用，子類別可覆寫並回傳為 false。
	 * @return
	 */
	protected boolean adoptQueueService() {
		return true;
	}
	
	/**
	 * 停止 Dispatcher 的運作(停止Dispatcher的相關thread運作)。
	 * 呼叫會停止在此方法，一直到thread完成關閉。
	 */
	public void destory() {
		if (this.unitQueueService != null) {
			if (this.unitQueueService.isWorking()) {
				this.unitQueueService.stopQueueService();
			}
		}
	}
	
	
	private class UnitQueueService extends QueueService<Unit> {
		private UnitQueueService() {
			super("Unit Dispatcher Queue Service");
		}
		
		@Override
		protected void newElementArrive(Unit unit) {
			execute(unit);
		}
	}
}
